package com.vince.hulk.states
{
import com.vince.hulk.character.Character;
import com.vince.hulk.character.Indicator;
import com.vince.hulk.mechanism.Fan;
import com.vince.hulk.mechanism.GameButton;
import com.vince.hulk.mechanism.IMechanism;
import com.vince.hulk.mechanism.MovableBlock;
import com.vince.hulk.mechanism.Switch;
import com.vince.hulk.ogmo.OgmoLevel;
import com.vince.hulk.menu.GameMenu;
import com.vince.hulk.menu.PauseMenu;

import flash.utils.Dictionary;

import org.flixel.FlxG;
import org.flixel.FlxGroup;
import org.flixel.FlxObject;
import org.flixel.FlxSound;
import org.flixel.FlxState;
import org.flixel.FlxText;
import org.flixel.FlxTilemap;
import org.flixel.FlxU;

/**
 * author yangwz
 */		
public class PlayState extends FlxState
{
	//==========================================================================
	//  Constructor
	//==========================================================================
	/**
	 * Constructs a new <code>PlayState</code> instance.
	 * 
	 */
	public function PlayState()
	{
		super();
	}
	//==========================================================================
	//  Variables
	//==========================================================================
	private var gameMusic:Class;
	
	private var SoundJump:Class;
	
	private var SoundButton:Class;
	
	private var SoundSplit:Class;
	
	private var SoundMerge:Class;
	
	private var SoundFan:Class;
	//==========================================================================
	//  Properties
	//==========================================================================
	/**
	 * 等级文本框 
	 */	
	public var levelName:FlxText;
	
	/**
	 * 时间文本框 
	 */	
	public var timeText:FlxText;
	
	public var _map1:FlxTilemap;
	
	public var mechanisms:FlxGroup;
	
	public var activeChar:int;
	
	public var finishCharSize:int;
	
	/**
	 * 保持当前所有绿巨人 
	 */	
	public var curChars:Array;
	
	public var nextLevelClass:Class;
	
	public var thisLevelClass:Class;
	
	public var characterGroup:FlxGroup;
	
	public var doors:FlxGroup;
	
	public var collidableMechanisms:FlxGroup;
	
	public var movingBlocks:FlxGroup;
	
	public var indicator:Indicator;
	
	public var blocks:FlxGroup;
	
	public var buttonPairs:Dictionary = new Dictionary();
	
	public var idleCounter:Number = 0;
	
	public var idleTime:Number = 0;
	
	public var loggingCounter:int = 1;
	
	/**
	 * 开关是否按下
	 */	
	public var switchIsHit:Boolean;
	
	/**
	 * 是否碰到风扇 
	 */	
	public var fanIsHit:Boolean;
	
	/**
	 * 暂停面板 
	 */	
	public var pause:PauseMenu;
	
	/**
	 * 两颗星所需时间 
	 */	
	public var twoStarTime:int;
	
	/**
	 * 三颗星所需时间 
	 */	
	public var threeStarTime:int;
	
	/**
	 * 游戏耗时 
	 */	
	public var totalTime:Number;
	//==========================================================================
	//  Methods
	//==========================================================================
	override public function create():void
	{
		totalTime = 0;
		mechanisms = new FlxGroup();
		collidableMechanisms = new FlxGroup();
		blocks = new FlxGroup();
		characterGroup = new FlxGroup();
		doors = new FlxGroup();
		movingBlocks = new FlxGroup();
		buttonPairs = new Dictionary();
		pause = new PauseMenu();
//		var sound:FlxSound = FlxG.play(gameMusic, 0.25, true, true);
		levelName = new FlxText(10, FlxG.height - 20, FlxG.width - 50);
		levelName.setFormat(null, 13);
		timeText = new FlxText(600, 900, 150, "");
		timeText.setFormat(null, 10);
//		sound.fadeIn(2);
		super.create();
	}
	
	/**
	 * 加载地图 
	 * @param param1
	 * @param param2
	 * @param param3
	 * @param param4
	 * @param param5
	 * 
	 */	
	public function loadMap(data:String, flxTilemap:FlxTilemap, clz:Class, tileWidth:int, tileHeight:int):void
	{
		var ogmoLevel:OgmoLevel = new OgmoLevel(data);
		new OgmoLevel(data).loadTiles(flxTilemap, clz, tileWidth, tileHeight);
		add(flxTilemap);
		ogmoLevel.loadSprites(curChars, mechanisms);
		indicator = new Indicator(0, 0);
		add(indicator);
		add(timeText);
		add(levelName);
	}
	
	/**
	 * 拆分绿巨人 
	 * @param character
	 */	
	private function splitChar(character:Character):void
	{
		var arr:Array = character.split();
		if (arr.length > 1)
		{
//			FlxG.play(SoundSplit);
		}
		remove(curChars[activeChar]);
		curChars.splice(activeChar, 1);
		curChars = curChars.concat(arr);
		activeChar = curChars.length - 1;
		for each (character in arr)
		{
			add(character);
		}
	}
	
	/**
	 * 切换 
	 */	
	private function toggleChar():void
	{
		curChars[activeChar].stopWalking();
		activeChar = (activeChar + 1) % curChars.length;
	}
	
	private function handleAnimations(character:Character):void
	{
	}
	
	override public function update():void
	{
		var _loc_2:Boolean = false;
		var _loc_3:int = 0;
		var character1:Character = null;
		var character2:Character = null;
		if (!pause.showing)
		{
			totalTime = totalTime + FlxG.elapsed;
			if (!FlxG.keys.any())
			{
				if (idleCounter >= 30)
				{
					idleTime = idleTime + FlxG.elapsed;
				}
				else
				{
					idleCounter = idleCounter + FlxG.elapsed;
				}
			}
			else
			{
				idleCounter = 0;
			}
		}
		var timeStr:String = FlxU.formatTime(totalTime, true);
		timeText.text = timeStr.substr(0, (timeStr.length - 1));
		if (5 * loggingCounter <= totalTime)
		{
			var playState:PlayState = this;
			var _loc_7:* = loggingCounter + 1;
			playState.loggingCounter = _loc_7;
//			if (Blob.CID >= 0)
//			{
//				Blob.getLogger().logAction(Blob.timeActionId, {time:this.totalTime, x:this.curChars[this.activeChar].x, y:this.curChars[this.activeChar].y, size:this.curChars[this.activeChar].size()});
//			}
		}
		if (!pause.showing)
		{
			switchIsHit = false;
			fanIsHit = false;
			collideCharactersWithMap();
			if (FlxG.keys.justPressed("SPACE"))
			{
				_loc_2 = false;
				_loc_3 = 0;
				while (_loc_3 < curChars.length)
				{
					
					if (_loc_3 != activeChar && curChars[_loc_3].overlaps(curChars[activeChar]))
					{
						character1 = curChars[activeChar].merge(curChars[_loc_3]);
						character2 = curChars[activeChar];
						if (character1 == null)
						{
							_loc_2 = true;
							break;
						}
//						FlxG.play(SoundMerge);
						add(character1);
						remove(curChars[_loc_3]);
						remove(curChars[activeChar]);
						if (_loc_3 > activeChar)
						{
							curChars.splice(_loc_3, 1);
							curChars.splice(activeChar, 1);
						}
						else
						{
							curChars.splice(activeChar, 1);
							curChars.splice(_loc_3, 1);
						}
						activeChar = curChars.push(character1) - 1;
						_loc_2 = true;
						break;
					}
					_loc_3++;
				}
				if (!_loc_2)
				{
					splitChar(curChars[activeChar]);
				}
				bringMechanismsToFront();
			}
			else if (FlxG.keys.justPressed("TAB") || FlxG.keys.justPressed("Q"))
			{
				toggleChar();
			}
			else if (FlxG.keys.justPressed("P"))
			{
				bringMechanismsToFront();
				pause = new PauseMenu();
				pause.showPaused();
				add(pause);
			}
			checkLevelFinished();
			_loc_3 = 0;
			while (_loc_3 < curChars.length)
			{
				
				if (curChars[_loc_3].x + curChars[_loc_3].width >= FlxG.width)
				{
					curChars[_loc_3].x = FlxG.width - curChars[_loc_3].width;
				}
				_loc_3++;
			}
			updateCharacter(curChars[activeChar] );
			indicator.x = curChars[activeChar].x + curChars[activeChar].width / 2 - indicator.width / 2;
			indicator.y = curChars[activeChar].y - 2 * indicator.height;
			super.update();
		}
		else
		{
			pause.update();
		}
	}
	
	public function bringMechanismsToFront():void
	{
		var len:int = 0;
		while (len < curChars.length)
		{
			
			remove(curChars[len]);
			add(curChars[len]);
			len++;
		}
		remove(collidableMechanisms);
		remove(mechanisms);
		add(collidableMechanisms);
		add(mechanisms);
	}
	
	public function updateCharacter(character:Character) : void
	{
		if (FlxG.keys.A || FlxG.keys.LEFT)
		{
			character.facing = FlxObject.LEFT;
			character.startWalking(true);
		}
		else if (FlxG.keys.D || FlxG.keys.RIGHT)
		{
			character.facing = FlxObject.RIGHT;
			character.startWalking(false);
		}
		else if (FlxG.keys.justReleased("A") || FlxG.keys.justReleased("LEFT") || FlxG.keys.justReleased("D") || FlxG.keys.justReleased("RIGHT"))
		{
			character.stopWalking();
		}
		if ((FlxG.keys.justPressed("W") || FlxG.keys.justPressed("UP")) && character.velocity.y == 0)
		{
			FlxG.play(this.SoundJump, 1, false, true);
			character.velocity.y = - character.jumpPower;
		}
		if (FlxG.keys.justPressed("R"))
		{
//			if (Blob.CID >= 0)
//			{
//				Blob.getLogger().logAction(Blob.resetActionId, {time:this.totalTime, x:this.curChars[this.activeChar].x, y:this.curChars[this.activeChar].y, size:this.curChars[this.activeChar].size()});
//			}
			FlxG.resetState();
		}
		if (FlxG.keys.justPressed("M"))
		{
			FlxG.switchState(new GameMenu());
			kill();
			pause.kill();
		}
	}
	
	/**
	 * 碰撞 
	 */	
	public function collideCharactersWithMap():void
	{
		var _loc_1:Object = null;
		var character:Character;
		var gameButton:GameButton = null;
		var _loc_4:Character = null;
		for (_loc_1 in buttonPairs)
		{
			
			gameButton = _loc_1 as GameButton;
			_loc_4 = buttonPairs[_loc_1] as Character;
			if (!FlxG.collide(_loc_4, gameButton))
			{
				gameButton.deactivate();
				delete buttonPairs[_loc_1];
			}
		}
		for each (character in curChars)
		{
			
			FlxG.collide(character, _map1);
			FlxG.collide(mechanisms, _map1);
			FlxG.collide(collidableMechanisms, collidableMechanisms);
			FlxG.collide(character, collidableMechanisms, activateMech);
			FlxG.collide(blocks, _map1);
			if (character.size() >= 2)
			{
				FlxG.collide(character, blocks, activateBlock);
			}
			else
			{
				FlxG.overlap(character, blocks, activateBlock);
			}
			FlxG.collide(movingBlocks, _map1);
			FlxG.collide(movingBlocks, character);
			FlxG.collide(movingBlocks, movingBlocks);
			FlxG.collide(blocks, blocks);
			FlxG.collide(blocks, movingBlocks);
			FlxG.collide(blocks, doors);
			FlxG.collide(movingBlocks, doors);
			FlxG.collide(doors, character);
			FlxG.collide(collidableMechanisms, _map1);
			FlxG.collide(collidableMechanisms, doors);
			FlxG.overlap(character, mechanisms, activateMech);
		}
	}
	
	public function activateMech(character:Character, mech:IMechanism) : void
	{
		var sound:FlxSound = null;
		var button:GameButton = null;
		var block:MovableBlock = null;
		if (mech is Switch && !switchIsHit && character == curChars[activeChar] && (FlxG.keys.justPressed("S") || FlxG.keys.justPressed("DOWN")))
		{
			mech.activate(character);
//			FlxG.play(SoundButton);
			switchIsHit = true;
		}
		else if (mech is Fan && !fanIsHit)
		{
			if (character.velocity.y < 0 && character.velocity.y > -60)
			{
//				_loc_3 = FlxG.play(SoundFan, 1, false, true);
				sound.fadeIn(0.5);
				sound.fadeOut(0.5);
			}
			mech.activate(character);
			fanIsHit = true;
		}
		else if (mech is GameButton)
		{
			button = mech as GameButton;
			if (!button.isActivated() && buttonPairs[character] != button)
			{
				mech.activate(character);
			}
		}
		else if (mech is MovableBlock)
		{
			block = mech as MovableBlock;
			block.lock();
			if (character.size() >= 2)
			{
				mech.activate(character);
			}
		}
		else if (!(mech is Switch))
		{
			mech.activate(character);
		}
	}
	
	public function activateBlock(character:Character, block:MovableBlock):void
	{
		movingBlocks.add(block);
		if (character.size() >= 2)
		{
			block.activate(character);
		}
		else
		{
			block.lock();
			block.activate(character);
		}
	}
	
	
	/**
	 * 检查等级到顶 
	 */	
	public function checkLevelFinished():void
	{
		if (curChars[activeChar].x + curChars[activeChar].width >= FlxG.width && curChars[activeChar].size() == finishCharSize)
		{
//			if (Blob.CID >= 0)
//			{
//				Blob.getLogger().logLevelEnd({QID:this.QID, finishTime:this.totalTime, idleTime:this.idleTime});
//			}
//			FlxG.switchState(new FinishedLevelState(thisLevelClass, nextLevelClass, totalTime, twoStarTime, threeStarTime, QID));
			pause.kill();
			kill();
		}
	}
}
}